import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author VernHe
 * @date 2021年08月24日 9:46
 */
public class Solution_0399 {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int equationsSize = equations.size();
        UnionFind unionFind = new UnionFind(equationsSize * 2);
        // 预处理，将遍历与id进行映射，用于并查集
        Map<String,Integer> hashMap = new HashMap<>(equationsSize * 2);
        int id = 0;
        for (int i = 0; i < equationsSize; i++) {
            List<String> equation = equations.get(i);
            String var1 = equation.get(0);
            String var2 = equation.get(1);
            // 放入map中
            if (!hashMap.containsKey(var1)) {
                hashMap.put(var1,id++);
            }
            if (!hashMap.containsKey(var2)) {
                hashMap.put(var2,id++);
            }
            // 进行合并
            unionFind.union(hashMap.get(var1), hashMap.get(var2), values[i]);
        }

        // 查询
        int queriesSize = queries.size();
        double[] res = new double[queriesSize];
        for (int i = 0; i < queriesSize; i++) {
            String var1 = queries.get(i).get(0);
            String var2 = queries.get(i).get(1);

            Integer id1 = hashMap.get(var1);
            Integer id2 = hashMap.get(var2);
            if (id1 == null || id2 == null) {
                res[i] = -1.0d;
            } else {
                res[i] = unionFind.isConnected(id1, id2);
            }
        }
        return res;
    }

    /**
     * 并查集
     */
    class UnionFind{
        /**
         * 保存父节点id
         */
        private int[] parent;
        /**
         * 指向父节点的权值
         */
        private double[] weight;

        /**
         * 构造函数
         * @param n
         */
        public UnionFind(int n) {
            this.parent = new int[n];
            this.weight = new double[n];
            // 初始化
            for (int i = 0; i < n; i++) {
                parent[i] = i;
                weight[i] = 1.0d;
            }
        }

        public void union(int x, int y, double value) {
            // 拿到根节点
            int rootX = find(x);
            int rootY = find(y);
            // 如果已经是一个集合的，就不进行操作
            if (rootX == rootY) {
                return;
            }
            // 跟新根节点和权值
            parent[rootX] = rootY;
            weight[rootX] = weight[y] * value / weight[x];
        }

        /**
         * 查找根节点并进行路劲压缩
         * @param x
         * @return  根节点
         */
        public int find(int x) {
            if (x != parent[x]) {
                int origin = parent[x];
                // 让x的父节点指向根节点
                parent[x] = find(parent[x]);
                weight[x] *= weight[origin];
            }
            return parent[x];
        }

        public double isConnected(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            // x,y是否是同一个集合
            if (rootX == rootY) {
                return weight[x] / weight[y];
            } else {
                return -1.0d;
            }
        }
    }
}
